package io.lvdaxian.mybatis12.scripting.defaults;

import com.alibaba.fastjson2.JSON;
import io.lvdaxian.mybatis12.builder.SqlSourceBuilder;
import io.lvdaxian.mybatis12.executor.parameter.ParameterHandler;
import io.lvdaxian.mybatis12.mapping.BoundSql;
import io.lvdaxian.mybatis12.mapping.MappedStatement;
import io.lvdaxian.mybatis12.mapping.ParameterMapping;
import io.lvdaxian.mybatis12.reflection.MetaObject;
import io.lvdaxian.mybatis12.session.Configuration;
import io.lvdaxian.mybatis12.type.JdbcType;
import io.lvdaxian.mybatis12.type.TypeHandler;
import io.lvdaxian.mybatis12.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * 表示 默认的设置参数的事件
 *
 * @author lihh
 */
public class DefaultParameterHandler implements ParameterHandler {
  
  private static final Logger logger = LoggerFactory.getLogger(SqlSourceBuilder.class);
  
  // 类型注册器
  private final TypeHandlerRegistry typeHandlerRegistry;
  // Mapped statement
  private final MappedStatement mappedStatement;
  // 参数对象
  private final Object parameterObject;
  // bound sql
  private BoundSql boundSql;
  // 配置文件
  private Configuration configuration;
  
  public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
    this.mappedStatement = mappedStatement;
    this.parameterObject = parameterObject;
    this.boundSql = boundSql;
    this.configuration = mappedStatement.getConfiguration();
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
  }
  
  @Override
  public Object getParameterObject() {
    return parameterObject;
  }
  
  @Override
  public void setParameters(PreparedStatement ps) throws SQLException {
    // 这里 拿到了参数映射
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    
    if (null == parameterMappings) return;
    
    for (int i = 0; i < parameterMappings.size(); i++) {
      // 拿到对应索引的值
      ParameterMapping parameterMapping = parameterMappings.get(i);
      // 属性名称
      String propertyName = parameterMapping.getProperty();
      Object value;
      // 这里就是 给 value 设置值
      // 如果是执行if 的分支的话，这个值将来是通过 handler 来处理的
      if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
        value = parameterObject;
      } else {
        // 通过 MetaObject.getValue 反射取得值设进去
        MetaObject metaObject = configuration.newMetaObject(parameterObject);
        value = metaObject.getValue(propertyName);
      }
      // jdbc 类型
      JdbcType jdbcType = parameterMapping.getJdbcType();
      
      // 设置参数
      logger.info("根据每个ParameterMapping中的TypeHandler设置对应的参数信息 value：{}", JSON.toJSONString(value));
      TypeHandler typeHandler = parameterMapping.getTypeHandler();
      typeHandler.setParameter(ps, i + 1, value, jdbcType);
    }
  }
}
